class Solution:
    def findOrder(self, numCourses: int, prerequisites: List[List[int]]) -> List[int]:
        def is_circle(course: int) -> bool:
            if visited[course]:
                return visited[course] == 2  # 值为1，回到正在搜索的节点，有环；值为2，遇到一个处理过的节点，这个节点的后续路径是无环的，无需再搜索。 
            visited[course] = 1   # 标记当前节点正在搜索
            for next_course in p[course]:
                if not is_circle(next_course):
                    return False  # 处理当前节点的所有下一个连接节点
            visited[course] = 2 # 该节点后续路径无环，比较为处理过
            res[self.idx] = course # DFS一定是将最后的节点先处理完毕，将处理完毕的节点加入结果表中
            self.idx -= 1
            return True

        p = [[] for _ in range(numCourses)] # 图连接矩阵
        res = [i for i in range(numCourses)]  # 初始学习顺序表，每个位置存放一个课程
        self.idx = numCourses -1 # 表索引，表示课程要添加的位置; 课程倒序添加
        # 根据先修课程关系生成图连接矩阵
        for (a, b) in prerequisites:
            p[b].append(a)
        # 枚举每一个节点为起点的路径进行dfs
        visited = [0] * numCourses
        for i in range(numCourses):
            if not visited[i] and not is_circle(i):
                return []  # 节点未访问过，说明是一条路径的起点，搜索该路径是否存在环
        return res